package lsl.leetCode.year2023.test0126;

import java.util.Arrays;
import java.util.HashMap;

/**
 * 两个数组的交集 II
 */
public class test350 {
    public static void main(String[] args) {
        int[] nums1 = {4, 9, 5};
        int[] nums2 = {9, 4, 9, 8, 4};
        intersectSecond(nums1, nums2);
    }

    //方法一：哈希表
    public static int[] intersectOne(int[] nums1, int[] nums2) {
        //由于同一个数字在两个数组中都可能出现多次，因此需要用哈希表存储每个数字出现的次数。
        HashMap<Integer, Integer> map = new HashMap<>();
        if (nums1.length > nums2.length) {
            //为了降低空间复杂度，首先遍历较短的数组并在哈希表中记录每个数字以及对应出现的次数，然后遍历较长的数组得到交集。
            return intersectOne(nums2, nums1);
        }
        //首先遍历第一个数组
        for (int num : nums1) {
            //在哈希表中记录第一个数组中的每个数字以及对应出现的次数
            int count = map.getOrDefault(num, 0) + 1;
            map.put(num, count);
        }
        int[] intersection = new int[nums1.length];
        int index = 0;
        //遍历第二个数组
        for (int num : nums2) {
            int count = map.getOrDefault(num, 0);
            if (count > 0) {
                //对于第二个数组中的每个数字，如果在哈希表中存在这个数字，则将该数字添加到答案，并减少哈希表中该数字出现的次数。
                intersection[index++] = num;
                count--;
                if (count > 0) {
                    map.put(num, count);
                } else {
                    map.remove(num);
                }
            }
        }
        //去掉多余的0
        return Arrays.copyOfRange(intersection, 0, index);
    }

    //方法二：排序+双指针---->如果两个数组是有序的，则可以使用双指针的方法得到两个数组的交集。
    public static int[] intersectSecond(int[] nums1, int[] nums2) {
        //先对数组排序
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int length1 = nums1.length, length2 = nums2.length;
        int[] intersection = new int[Math.min(length1, length2)];
        //数组1的指针
        int index1 = 0;
        //数组2的指针
        int index2 = 0;
        //结果数组的大小
        int index = 0;
        //当至少有一个指针超出数组范围时，遍历结束。
        while (index1 < length1 && index2 < length2) {
            //每次比较两个指针指向的两个数组中的数字，如果两个数字不相等，则将指向较小数字的指针右移一位
            if (nums1[index1] > nums2[index2]) {
                index2++;
            } else if (nums2[index2] > nums1[index1]) {
                index1++;
            } else {
                //如果两个数字相等，将该数字添加到答案，并将两个指针都右移一位
                intersection[index++] = nums2[index2];
                index1++;
                index2++;
            }
        }
        return Arrays.copyOfRange(intersection, 0, index);
    }
}
